package ldh.im.fxgui.service;

import com.google.common.reflect.TypeToken;
import ldh.im.fxbase.pojo.ResponseResult;
import ldh.im.fxbase.util.HttpClientUtil;
import ldh.im.fxbase.util.LoggerUtil;
import ldh.im.fxgui.Api;
import ldh.im.fxgui.dto.LoginDto;
import ldh.im.util.JsonUtil;
import org.apache.commons.lang3.StringUtils;

import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.logging.Level;
import java.util.logging.Logger;

public class HttpService {

    private static final Logger LOGGER = LoggerUtil.getFileLogger(HttpService.class);
    private static final String REFRESH_TOKEN = "refreshToken";

    private static Map<String, String> refreshTokenMap = new ConcurrentHashMap<>();

    public static <T>T get(String url, Map<String, Object> params) throws Exception {
        String json = catchException(()->HttpClientUtil.get(url, params, initHeader()));
        ResponseResult<T> responseResult = JsonUtil.toObject(json, new TypeToken<ResponseResult<T>>(){}.getType());
        if (responseResult.getStatus() == -100) { // 超时
            String refreshToken = refreshTokenMap.get(REFRESH_TOKEN);
            if (StringUtils.isEmpty(refreshToken)) {
                throw new RuntimeException("请重新登录");
            }
            refreshToken();
            return get(url, params);
        }
        if (responseResult.isSuccess()) {
            return responseResult.getData();
        }
        throw new RuntimeException(responseResult.getMsg());
    }

    public static <T>T post(String url, Map<String, Object> params) throws Exception {
        String json = catchException(()->HttpClientUtil.post(url, params, initHeader()));
        ResponseResult<T> responseResult = JsonUtil.toObject(json, new TypeToken<ResponseResult<T>>(){}.getType());
        if (responseResult.getStatus() == -100) { // 超时
            String refreshToken = refreshTokenMap.get("refreshToken");
            if (StringUtils.isEmpty(refreshToken)) {
                throw new RuntimeException("请重新登录");
            }
            refreshToken();
            return post(url, params);
        }

        if (responseResult.isSuccess()) {
            return responseResult.getData();
        }
        throw new RuntimeException(responseResult.getMsg());
    }

    public static LoginDto login(String userName, String password) throws Exception {
        Map<String, Object> params = new HashMap();
        params.put("name", userName);
        params.put("password", password);
        String result = catchException(()->HttpClientUtil.post(Api.LOGIN_URL, params));
        LOGGER.info("login result:" + result);
        ResponseResult<LoginDto> responseResult = JsonUtil.toObject(result, new TypeToken<ResponseResult<LoginDto>>(){}.getType());
        if (responseResult.isSuccess()) {
            loginSuccess(responseResult.getData());
            return responseResult.getData();
        }
        LOGGER.severe("登录失败" + responseResult.getMsg());
        throw new RuntimeException("登录失败");
    }

    private static void refreshToken() throws Exception {
        String refreshToken = refreshTokenMap.get(REFRESH_TOKEN);
        Map<String, Object> params = new HashMap();
        params.put("refreshToken", refreshToken);
        String result = catchException(()->HttpClientUtil.post(Api.LOGIN_REFRESH_URL, params));
        LOGGER.info("login result:" + result);
        ResponseResult<LoginDto> responseResult = JsonUtil.toObject(result, new TypeToken<ResponseResult<LoginDto>>(){}.getType());
        if (responseResult.isSuccess()) {
            loginSuccess(responseResult.getData());
        }
        LOGGER.severe("登录失败" + responseResult.getMsg());
        throw new RuntimeException("登录失败");
    }

    private static Map<String, Object> initHeader() {
        Map<String, Object> headers = new HashMap();
        headers.put("im.token", refreshTokenMap.get("token"));
        return headers;
    }

    private static void loginSuccess(LoginDto loginDto) {
        refreshTokenMap.put(REFRESH_TOKEN, loginDto.getRefreshToken());
        refreshTokenMap.put("token", loginDto.getToken());
    }

    private static <T>T catchException(RequestServer<T> supplier) {
        try {
            return supplier.request();
        } catch (Exception e) {
            LOGGER.log(Level.SEVERE, "服务器异常", e);
            throw new RuntimeException("服务器异常");
        }
    }

    private static interface RequestServer<T> {
        T request() throws Exception;
    }
}
